package cn.tedu.charging.order.service.impl;

import cn.tedu.charging.common.pojo.JsonResult;
import cn.tedu.charging.common.pojo.param.GunStatusUpdateParam;
import cn.tedu.charging.common.pojo.vo.StationInfoVO;
import cn.tedu.charging.common.pojo.vo.UserInfoVO;
import cn.tedu.charging.common.utils.JsonUtils;
import cn.tedu.charging.order.common.ChargingConstants;
import cn.tedu.charging.order.common.MqttConstants;
import cn.tedu.charging.order.feign.DeviceClient;
import cn.tedu.charging.order.feign.UserClient;
import cn.tedu.charging.order.mqtt.MqttProducer;
import cn.tedu.charging.order.pojo.dto.ChargingDto;
import cn.tedu.charging.order.pojo.po.OrderMQPO;
import cn.tedu.charging.order.quartz.DeviceCheckJob;
import cn.tedu.charging.order.rabbitmq.RabbitMQProducer;
import cn.tedu.charging.order.service.OrderService;
import cn.tedu.charging.order.pojo.param.OrderAddParam;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private UserClient userClient;

    @Autowired
    private DeviceClient deviceClient;

    @Autowired
    private MqttProducer mqttProducer;
    @Override
    public String createOrder(OrderAddParam orderAddParam) {
        log.debug("创建订单业务，参数：{}",orderAddParam);
        // 1 生成订单号
        log.debug("创建订单业务-生成订单号");
        String orderNo=getOrderNo();
        log.debug("创建订单业务-生成订单号-结果：{}",orderNo);
        // 2 更新枪的状态
        log.debug("创建订单业务-更新枪的状态:{}",orderAddParam.getGunId());
        Boolean success=updateGunStatus(orderAddParam.getGunId());
        log.debug("创建订单业务-更新枪的状态:入参{},结果：{}",orderAddParam.getGunId(),success);
        // 3. 获取用户信息 通过Feign调用userService获取用户的车辆信息
        log.debug("创建订单业务-获取用户信息:{}",orderAddParam.getUserId());
        UserInfoVO userInfoVO = getUserInfo(orderAddParam.getUserId());
        log.debug("创建订单业务-获取用户信息:入参{},结果：{}",orderAddParam.getUserId(),userInfoVO);
        // 4. 获取场站信息
        log.debug("创建订单业务-获取场站信息:{}",orderAddParam.getGunId());
        StationInfoVO stationInfoVO = getStationInfo(orderAddParam.getGunId());
        log.debug("创建订单业务-获取场站信息:入参{},结果：{}",orderAddParam.getGunId(),stationInfoVO);

        // 5. 需要向设备发送指令，让物理设备根据设备信息给用户充电
        // 将方法抽离出来，在此调用
        log.debug("创建订单业务-发送开始充电指令到设备,传参:{}",orderNo,orderAddParam.getPileId(),orderAddParam.getGunId(),stationInfoVO.getOperatorId());
        ChargingDto chargingDto = new ChargingDto();
        chargingDto.setOrderNo(orderNo);
        chargingDto.setPileId(orderAddParam.getPileId());
        chargingDto.setGunId(orderAddParam.getGunId());
        chargingDto.setOperatorId(stationInfoVO.getOperatorId());
        chargingDto.setVehicleId(userInfoVO.getVehicleId());
        startCharging(chargingDto);
        log.debug("创建订单业务-发送开始充电指令到设备入参:{},出参:{}",orderNo,orderAddParam.getPileId(),orderAddParam.getGunId());
        // 6. 给消息队列发送一个带有生存时间的消息，生存时间是电池充满电所需要的时间
        log.debug("创建订单-给消息队列发送有生存时间的消息:{}",orderNo);
        Boolean sendMessageResult = sendMessage(orderNo);
        log.debug("创建订单-给消息队列发送有生存时间的消息:{},结果:{}",orderNo,sendMessageResult);

        // 设置定时任务，解决设备无响应的问题，由于设备可能不会有返回结果，所以需要设置定时任务，且Mqtt的回调也可能出现问题
        log.debug("创建订单业务-设置定时任务,入参:{},出参:{}",orderNo,orderAddParam.getGunId());
        try {
            DeviceCheckJob deviceCheckJob = new DeviceCheckJob(orderNo,orderAddParam.getGunId());
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
        log.debug("创建订单业务-设置定时任务,入参:{},结果:{}",orderNo,orderAddParam.getGunId());

        log.debug("创建订单业务，参数{},结果{}",orderAddParam,orderNo);
        return orderNo;
    }


    private void startCharging(ChargingDto chargingDto){
        // 设计Topic
        // 使用充电桩维度 相比于充电桩维度，可以减少Topic的数量
        log.debug("订单服务发送开始充电指令到设备topic:{}，入参:{}",chargingDto);
        String topic = MqttConstants.TOPIC_START_CHARGING_PREFIX +chargingDto.getPileId();
        //ChargingDto chargingDto = new ChargingDto();
        /*chargingDto.setOrderNo(orderNo);
        chargingDto.setPileId(pileId);
        chargingDto.setGunId(gunId);
        chargingDto.setOperatorId(operatorId);*/
        chargingDto.setMsg(ChargingConstants.START_CHARGING);
        // json 格式的数据转换
        String massage = JsonUtils.toJson(chargingDto);
        log.debug("订单服务发送开始充电指令到设备topic:{}",topic,massage);
        Boolean success = mqttProducer.send(topic, massage);
        log.debug("订单服务发送开始充电指令到设备topic:{},消息:{},结果:{}",topic,massage,success);

    }

    @Autowired
    private RabbitMQProducer rabbitMQProducer;
    private Boolean sendMessage(String orderNo){
        OrderMQPO orderMQPO = new OrderMQPO();
        orderMQPO.setOrderNo(orderNo);
        rabbitMQProducer.publish(orderMQPO);
        return true;
    }

    private String getOrderNo(){
        return "666";
    }
    private Boolean updateGunStatus(Integer gunId){
        GunStatusUpdateParam gunStatusUpdateParam = new GunStatusUpdateParam();
        gunStatusUpdateParam.setGunId(gunId);
        gunStatusUpdateParam.setStatus(1);// 应该定义为常量或者枚举
        Boolean success=deviceClient.updateGunStatus(gunStatusUpdateParam).getData();
        return success;
    }

    private UserInfoVO getUserInfo(Integer userId){
        JsonResult<UserInfoVO> userInfo = userClient.getUserInfo(userId);
        if (userInfo != null){
            return userInfo.getData();
        }
        return null;
    }

    private StationInfoVO getStationInfo(Integer gunId){
        JsonResult<StationInfoVO> stationInfo = deviceClient.getStationInfo(gunId);
        if (stationInfo != null){
            return stationInfo.getData();
        }
        return null;
    }
}
